﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using AssetLoad;
using Dict.DataModel;
using Dict.Blo;

public class FormationResourceCache : MonoBehaviour
{
    private List<string> heroCache = new List<string>();
    private Dictionary<string, List<string>> resourceUrls = new Dictionary<string, List<string>>();
    private Dictionary<string, List<string>> audioUrls = new Dictionary<string, List<string>>();
    private Dictionary<string, string> extendResource = new Dictionary<string, string>();
    private string particleRes = "particles/";
    private string ultiPath = "ultimate/";

    public void ReplaceHero(string addHero, string removeHero)
    {
        if (addHero == removeHero)
        {
            return;
        }
        if (!heroCache.Contains(addHero))
        {
            LoadHero(addHero);
        }
        if (heroCache.Contains(removeHero))
        {
            UnloadHero(removeHero);
        }
    }

    private void UnloadHero(string removeHero)
    {
        heroCache.Remove(removeHero);
        if (resourceUrls.ContainsKey(removeHero))
        {
            foreach (var url in resourceUrls[removeHero])
            {
#if !FIX_RESOURCE
                GameObjectPoolManager.Instance.UnRegist(url, CommonMethod.GetAssetNameFromAssetBundleName(url));
                AssetBundleManager.Instance.UnloadAssetBundle(url);
#else
                GameObjectPoolManager.Instance.UnRegist(url);
                ResourceManager.Instance.UnloadResource(url);
#endif
            }
            resourceUrls[removeHero].Clear();
            resourceUrls.Remove(removeHero);

        }

        if (extendResource.ContainsKey(removeHero))
        {
            AssetBundleManager.Instance.UnloadAssetBundle(extendResource[removeHero]);
            extendResource.Remove(removeHero);
        }
        if (audioUrls.ContainsKey(removeHero))
        {
            foreach (var url in audioUrls[removeHero])
            {
                AudioManager.Instance.UnloadAudioResource(url);
            }
            audioUrls[removeHero].Clear();
            audioUrls.Remove(removeHero);
        }

    }

    public void LoadHero(string addHero)
    {
        heroCache.Add(addHero);
        StartCoroutine(LoadHeroAsync(addHero));
    }

    private IEnumerator LoadHeroAsync(string heroId)
    {
        if (!heroCache.Contains(heroId) || resourceUrls.ContainsKey(heroId))
        {
            yield break;
        }
        resourceUrls[heroId] = new List<string>();
        audioUrls[heroId] = new List<string>();
        TableHero tb = DictHeroBlo.GetTableHero(heroId);
        resourceUrls[heroId].Add("model/" + tb.resName);

#if !FIX_RESOURCE
        AssetBundleManager.Instance.LoadAssetBundle(("model/" + tb.resName).ToLower());
        while (!AssetBundleManager.Instance.IsLoadedAssetBundle(("model/" + tb.resName).ToLower()))
        {
            yield return null;
        }
        GameObjectPoolManager.Instance.Regist("model/" + tb.resName, tb.resName);
#else
        ResourceManager.Instance.LoadResource(@"model/" + tb.resName);
        GameObjectPoolManager.Instance.Regist(@"model/" + tb.resName);
#endif
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            Debug.LogWarning("cache not exist " + heroId);
            yield break;
        }
        AssetBundleManager.Instance.LoadAssetBundle("model/" + tb.resName + ConstData.extendResPostfix);
        while (!AssetBundleManager.Instance.IsLoadedAssetBundle("model/" + tb.resName + ConstData.extendResPostfix))
        {
            yield return null;
        }
        AssetBundleManager.Instance.GetAssetFromBundle("model/" + tb.resName + ConstData.extendResPostfix,tb.resName+ConstData.extendResPostfix,typeof(AnimClipsAsset));
        if (!heroCache.Contains(heroId))
        {
            Debug.LogWarning("cache not exist " + heroId);
            yield break;
        }
        extendResource.Add(heroId, "model/" + tb.resName + ConstData.extendResPostfix);
        yield return StartCoroutine(LoadSkill(heroId, tb.SkillId1));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            Debug.LogWarning("cache not exist " + heroId);
            yield break;
        }
        yield return StartCoroutine(LoadSkill(heroId, tb.SkillId2));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            Debug.LogWarning("cache not exist " + heroId);
            yield break;
        }
        yield return StartCoroutine(LoadSkill(heroId, tb.UltSkillId));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            Debug.LogWarning("cache not exist " + heroId);
            yield break;
        }
        StartCoroutine(LoadUltimateSkill(heroId, tb.UltSkillId));
    }

    private IEnumerator LoadParticle(string heroId, string particleId)
    {
        if (!string.IsNullOrEmpty(particleId) && resourceUrls.ContainsKey(heroId))
        {
            TableParticle tp = DictParticleBlo.GetParticle(particleId);
            if (tp != null)
            {
                //Debug.Log("pre load particle " + heroId + " " + tp.ResourcePath);
                string path = particleRes + tp.ResourcePath;
                resourceUrls[heroId].Add(path);
#if !FIX_RESOURCE
                AssetBundleManager.Instance.LoadAssetBundle(path);
                while (!AssetBundleManager.Instance.IsLoadedAssetBundle(path))
                {
                    yield return null;
                }
                GameObjectPoolManager.Instance.Regist(path, CommonMethod.GetAssetNameFromAssetBundleName(path));
#else
                ResourceManager.Instance.LoadResource(path);
                GameObjectPoolManager.Instance.Regist(path);
                yield return 0;
#endif
            }
            else
            {
                Debug.LogError("particle id " + particleId + " not exist ");
            }
        }

    }

    private IEnumerator LoadPaintParticle(string heroId, string paint)
    {
        //Debug.Log("pre load painter " + heroId + " " + paint);
        if (!string.IsNullOrEmpty(paint) && resourceUrls.ContainsKey(heroId))
        {
            resourceUrls[heroId].Add(paint);
#if !FIX_RESOURCE
            AssetBundleManager.Instance.LoadAssetBundle(paint);
            while (!AssetBundleManager.Instance.IsLoadedAssetBundle(paint))
            {
                yield return null;
            }
            GameObjectPoolManager.Instance.Regist(paint, CommonMethod.GetAssetNameFromAssetBundleName(paint));
#else
            ResourceManager.Instance.LoadResource(paint);
            GameObjectPoolManager.Instance.Regist(paint);
            yield return 0;
#endif
        }
    }

    private IEnumerator LoadUltiParticle(string heroId, string url)
    {
        //Debug.Log("pre load ultimate " + heroId + " " + url);
        if (!string.IsNullOrEmpty(url) && resourceUrls.ContainsKey(heroId))
        {
            string path = ultiPath + url;
            resourceUrls[heroId].Add(path);
#if !FIX_RESOURCE
            AssetBundleManager.Instance.LoadAssetBundle(path);
            while (!AssetBundleManager.Instance.IsLoadedAssetBundle(path))
            {
                yield return null;
            }
            GameObjectPoolManager.Instance.Regist(path, CommonMethod.GetAssetNameFromAssetBundleName(path));
#else
            ResourceManager.Instance.LoadResource(path);
            GameObjectPoolManager.Instance.Regist(path);
            yield return 0;
#endif
        }
    }

    private IEnumerator LoadSkill(string heroId, string skillId)
    {
        TableSkill ts = DictHeroSkillBlo.GetTalbeSkill(skillId);
        if (ts == null)
        {
            Debug.LogError("skill id: " + skillId + " not exist!");
            yield break;
        }
        yield return StartCoroutine(LoadParticle(heroId, ts.Effect0));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        yield return StartCoroutine(LoadParticle(heroId, ts.Effect1));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        yield return StartCoroutine(LoadParticle(heroId, ts.Effect2));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        yield return StartCoroutine(LoadParticle(heroId, ts.Effect3));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        if (!string.IsNullOrEmpty(ts.SkillAudio))
        {
            audioUrls[heroId].Add(ts.SkillAudio);
            yield return StartCoroutine(AudioManager.Instance.LoadAudioResource(ts.SkillAudio));
            yield return 1;
            if (!heroCache.Contains(heroId))
            {
                yield break;
            }
        }

        List<TableSkillCast> castList = DictHeroSkillBlo.GetTableSkillCastByHSId(ts.SkillId);
        for (int i = 0; i < castList.Count; ++i)
        {
            var cast = castList[i];
            yield return StartCoroutine(LoadParticle(heroId, cast.GroundEffect));
            yield return 1;
            if (!heroCache.Contains(heroId))
            {
                yield break;
            }
            yield return StartCoroutine(LoadParticle(heroId, cast.BehitEffSelf));
            yield return 1;
            if (!heroCache.Contains(heroId))
            {
                yield break;
            }
            yield return StartCoroutine(LoadParticle(heroId, cast.BehitEffectEnemy));
            yield return 1;
            if (!heroCache.Contains(heroId))
            {
                yield break;
            }
            yield return StartCoroutine(LoadParticle(heroId, cast.ProjectId));
            yield return 1;
            if (!heroCache.Contains(heroId))
            {
                yield break;
            }
            if (!string.IsNullOrEmpty(cast.BehitAudio))
            {
                audioUrls[heroId].Add(cast.BehitAudio);
                yield return StartCoroutine(AudioManager.Instance.LoadAudioResource(cast.BehitAudio));
                yield return 1;
                if (!heroCache.Contains(heroId))
                {
                    yield break;
                }
            }
        }
    }

    private IEnumerator LoadUltimateSkill(string heroId, string skillId)
    {
        var dict = Dict.Blo.DictHeroSkillBlo.GetTableUltimateSkill(skillId);
        if (dict == null)
        {
            Debug.LogError("ultimate skill id: " + skillId + " not exist!");
            yield break;
        }
        //Debug.Log(heroId + " ultimate " + dict.FinalBeHitEffect + " " + dict.EffectResourceName + " " + dict.PaintResUrl);
        yield return StartCoroutine(LoadParticle(heroId, dict.FinalBeHitEffect));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        yield return StartCoroutine(LoadUltiParticle(heroId, dict.EffectResourceName));
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
        yield return LoadPaintParticle(heroId, dict.PaintResUrl);
        yield return 1;
        if (!heroCache.Contains(heroId))
        {
            yield break;
        }
    }

    public void Clear()
    {
        StopAllCoroutines();
        for (int i = heroCache.Count; i < heroCache.Count; --i)
        {
            UnloadHero(heroCache[i]);
        }
        heroCache.Clear();
        resourceUrls.Clear();
        audioUrls.Clear();
        extendResource.Clear();
    }
}
